interface BaseResponse<T> {
  code: number;
  data: T;
  message: string;
}

const DEFAULT_HEADERS: HeadersInit = {
  'Content-Type': 'application/json',
};

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? '';

async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
  const response = await fetch(withBase(path), {
    ...init,
    headers: buildHeaders(init.headers),
  });

  if (!response.ok) {
    const text = await response.text();
    throw new Error(text || `请求失败（${response.status}）`);
  }

  const contentType = response.headers.get('content-type') ?? '';
  if (!contentType.includes('application/json')) {
    // 直接返回非 JSON 结果，例如文件流
    return (await response.text()) as unknown as T;
  }

  const payload = (await response.json()) as BaseResponse<T> | T;

  if (isBaseResponse<T>(payload)) {
    if (payload.code !== 200) {
      throw new Error(payload.message || '请求失败');
    }
    return payload.data;
  }

  return payload as T;
}

function buildHeaders(headers?: HeadersInit): HeadersInit {
  if (!headers) {
    return DEFAULT_HEADERS;
  }
  const result = new Headers(DEFAULT_HEADERS);
  const incoming = new Headers(headers);
  incoming.forEach((value, key) => result.set(key, value));
  return result;
}

function withBase(path: string): string {
  if (path.startsWith('http://') || path.startsWith('https://')) {
    return path;
  }
  return `${API_BASE_URL}${path}`;
}

function isBaseResponse<T>(payload: unknown): payload is BaseResponse<T> {
  return (
    typeof payload === 'object' &&
    payload !== null &&
    'code' in payload &&
    'data' in payload
  );
}

export const api = {
  get<T>(path: string): Promise<T> {
    return request<T>(path, { method: 'GET' });
  },
  post<T>(path: string, body: unknown): Promise<T> {
    return request<T>(path, {
      method: 'POST',
      body: JSON.stringify(body ?? {}),
    });
  },
};

export type { BaseResponse };

